package com.tron.dobest.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

import java.util.Arrays;

@Component
@Aspect
@Slf4j
public class TronAop {

    @Pointcut("execution(* com.tron.dobest.aop.TronAopTestController.aopTest01(..))")
    public void tronPointcutOne() {}

    @Before("tronPointcutOne()")
    public void beforeMethod() {
        log.info("======beforeMethod======");
    }

    @After("tronPointcutOne()")
    public void afterMethod() {
        log.info("======afterMethod======");
    }

    @AfterReturning("tronPointcutOne()")
    public void afterReturn() {
        log.info("======afterReturn======");
    }

    @AfterThrowing(pointcut = "tronPointcutOne()",throwing = "ex")
    public void afterThrowing(Throwable ex) {
        log.info("======afterThrowing======"+ex.getMessage());
    }

    /**
     * 环绕写法
     */
    @Pointcut("execution(* com.tron.dobest.aop.TronAopTestController.aopTest02(..))")
    public void tronPointcutTwo() {}

    @Around("tronPointcutTwo()")
    public Object around(ProceedingJoinPoint joinPoint) {
        Object result = null;
        StopWatch stopWatch = new StopWatch();
        try {
            stopWatch.start();
            Object[] args = joinPoint.getArgs();
            log.info("======AOP方法环绕前====== statTime:{},args:{}",stopWatch.getTotalTimeMillis(), Arrays.asList(args));
            result = joinPoint.proceed();
            stopWatch.stop();
            log.info("======AOP方法环绕后====== endTime:{},result:{}",stopWatch.getTotalTimeMillis(),result);
        } catch (Throwable throwable) {
            log.info("======AOP方法环绕异常======exception:{}",throwable.getMessage());
        }
        return result;
    }


    //所有公共方法
    @Pointcut("execution(public * *(..))")
    public void anyPublicOperation(){};

    //拦截TronAopTestController类的所有方法
    @Pointcut("within(com.tron.dobest.aop.TronAopTestController)")
    public void inSomeMethod(){};

    //执行方法带有@Transactional注释的任何连接点
    @Pointcut("within(org.springframework.transaction.annotation.Transactional)")
    public void witchAnnotation(){};

    //执行方法带有@Transactional注释的任何连接点
    @Pointcut("@annotation(org.springframework.transaction.annotation.Transactional)")
    public void witchAnnotation1(){};

    //Spring bean上的任何连接点
    @Pointcut("bean(tronAopTestController)")
    public void witchBean(){};

    //Spring bean上的任何连接点
    @Pointcut("bean(*tronAopTestController)")
    public void witchService(){};

    //拦截TronAopTestController类的所有public方法
    @Before("inSomeMethod() && anyPublicOperation() ")
    public void BeforeInSomeMethod() {
        log.info("======within(com.tron.dobest.aop.TronAopTestController)======");
    }

    @Before("witchBean()")
    public void BeforeWitchBean() {
        log.info("======bean(tronAopTestController)======");
    }

    @Before("witchService()")
    public void BeforeWitchService() {
        log.info("======witchService()======");
    }


}
